package com.kanas.webak.admin.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.inject.Singleton;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import com.kanas.framework.business.BusinessException;
import com.kanas.framework.util.Security;
import com.kanas.webak.admin.domain.AppUser;
import com.kanas.webak.admin.exception.SysUserException;
import com.kanas.webak.admin.repository.UserRepository;
import com.kanas.webak.organization.domain.Organization;
import com.kanas.webak.organization.repository.OrganizationRepository;
import com.kanas.webak.rbac.domain.AppRole;
import com.kanas.webak.rbac.domain.AppUserRole;
import com.kanas.webak.rbac.repository.RoleRepository;
import com.kanas.webak.rbac.repository.UserRoleRepository;
import com.kanas.webak.rbac.service.ServiceException;

@Service("kanas.admin.service.sysuserservice")
@Singleton
public class UserServiceImpl implements UserService{

	@Autowired
	private UserRepository userRepository;
	@Autowired
	private RoleRepository roleRepository;
	@Autowired
	private UserRoleRepository userRoleRepository;
	@Autowired
	private OrganizationRepository orgRepository;
	
	@Override
	@Transactional
	public String resetPassword(String uid)throws Exception {
		AppUser user = this.userRepository.findOne(uid);
		if(user == null)throw ServiceException.DATA_NOT_FOUND;
		String password = Security.digest32HexSHA1("123456{"+user.getId()+"}");
		user.setPassword(password);
		this.userRepository.save(user);
		return uid;
	}
	
	@Override
	@Transactional
	public String delete(String uid)throws Exception {
		AppUser user = this.userRepository.findOne(uid);
		if(user == null)throw ServiceException.DATA_NOT_FOUND;
		this.userRepository.delete(user);
		return uid;
	}

	@Override
	@Transactional
	public AppUser findOne(String userId) {
		AppUser au= this.userRepository.findOne(userId);
		return au;
	}
	
	@Override
	@Transactional
	public Page<AppUser> findAll(Pageable pageable) {
		return this.userRepository.findAll(pageable);
	}
	
	@Override
	@Transactional
	public Page<AppUser> findByRole(Pageable pageable,String roleId) {
		return this.userRepository.findByRoleId(roleId,pageable);
	}
	
	@Override
	@Transactional
	public String update(String userId,AppUser user,String roleIds) {
		AppUser u = userRepository.findOne(userId);
		u.setActiveFlag(user.getActiveFlag());
		u.setDisplayName(user.getDisplayName());
		u.setExpiredFlag(user.getExpiredFlag());
		u.setLockedFlag(user.getLockedFlag());
		String[] ids = roleIds.split(",");
		Iterable<AppRole> roles = roleRepository.findByIdIn(Arrays.asList(ids));
		Set<AppRole> rs = new HashSet<AppRole>();
		for(AppRole role:roles){
			rs.add(role);
		}
		this.userRepository.save(u);
		return userId;
	}
	
	@Override
	@Transactional
	public String disable(String userId){
		AppUser u = userRepository.findOne(userId);
		u.setActiveFlag(false);
		this.userRepository.save(u);
		return userId;
	}
	
	@Override
	@Transactional
	public Long count() {
		return this.userRepository.count();
	}
	
	@Override
	@Transactional
	public String addNew(AppUser user,String roleIds) throws Exception {
		{
			AppUser u = userRepository.findByUsername(user.getUsername());
			if(u!=null)throw BusinessException.DATA_DUPLICATION;
		}
		
		String[] ids = roleIds.split(",");
		Iterable<AppRole> roles = roleRepository.findByIdIn(Arrays.asList(ids));
		Set<AppRole> rs = new HashSet<AppRole>();
		for(AppRole role:roles){
			rs.add(role);
		}
		
		String pw=user.getPassword()+"{"+user.getId()+"}";
		String password = Security.digest32HexSHA1(pw);
		user.setPassword(password);
		Date now=new Date();
		user.setCreateDate(now);
		userRepository.save(user);
		return user.getId();
	}
	
	@Override
	@Transactional
	public String changePsd(String oldPsd, String newPsd)throws Exception {
		AppUser user = (AppUser)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		String oldPassword = Security.digest32HexSHA1(oldPsd + "{" + user.getId() + "}");
		if(!oldPassword.equals(user.getPassword()))throw SysUserException.OLD_PASSWORD_FAILED;
		String newPassword = Security.digest32HexSHA1(newPsd + "{" + user.getId() + "}");
		user.setPassword(newPassword);
		userRepository.save(user);
		return user.getId();
	}

	@Override
	@Transactional
	public List<AppUserRole> findUserRoles(String id, String orgId) {
		List<AppUserRole> urs = new ArrayList<AppUserRole>();
		if(id==null || orgId==null) return urs; 
		AppUser user = userRepository.findOne(id);
		Organization org = orgRepository.findOne(orgId);
		if(user==null || org==null) return urs;
		urs = userRoleRepository.findByUserAndOrganization(user, org);
		for(AppUserRole ur:urs) {
			ur.setRoleLabel(ur.getRole().getLabel());
			ur.setUsername(ur.getUser().getUsername());
			ur.setOrgLabel(ur.getOrganization()==null?"":ur.getOrganization().getLabel());
		}
		return urs;
	}

	@Override
	@Transactional
	public List<AppRole> findRoles(String id, String orgId) {
		List<AppRole> ars = new ArrayList<AppRole>();
		List<AppUserRole> aus = this.findUserRoles(id, orgId);
		for(AppUserRole au:aus) {
			ars.add(au.getRole());
		}
		return ars;
	}
	
	public UserRepository getUserRepository() {
		return userRepository;
	}

	public void setUserRepository(UserRepository userRepository) {
		this.userRepository = userRepository;
	}
	
	public RoleRepository getRoleRepository() {
		return roleRepository;
	}

	public void setRoleRepository(RoleRepository roleRepository) {
		this.roleRepository = roleRepository;
	}

	public OrganizationRepository getOrgRepository() {
		return orgRepository;
	}

	public void setOrgRepository(OrganizationRepository orgRepository) {
		this.orgRepository = orgRepository;
	}

	public UserRoleRepository getUserRoleRepository() {
		return userRoleRepository;
	}

	public void setUserRoleRepository(UserRoleRepository userRoleRepository) {
		this.userRoleRepository = userRoleRepository;
	}
	
	@Override
	public String removeRole(AppUser u) {
		// TODO Auto-generated method stub
		return null;
	}
}